'/
' SHA-256 hashing
' --------------------------------------------------------------------------------
' Sha256.bmx
' 
' Found in the Code archives at www.blitzbasic.com
'/


'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'// 		Returns a SHA-256 hash.
'// 
'// Parameters:
'//		(string) in: The source string from which to create the hash.
'// -----------------------------------------------------------------------------------------------------------------
function sha256:string(in:string)

	local h0:int = $6A09E667, h1 = $BB67AE85, h2 = $3C6EF372, h3 = $A54FF53A
	local h4:int = $510E527F, h5 = $9B05688C, h6 = $1F83D9AB, h7 = $5BE0CD19
	
	local k:int[] = [$428A2F98, $71374491, $B5C0FBCF, $E9B5DBA5, $3956C25B, $59F111F1, ..
	                 $923F82A4, $AB1C5ED5, $D807AA98, $12835B01, $243185BE, $550C7DC3, ..
	                 $72BE5D74, $80DEB1FE, $9BDC06A7, $C19BF174, $E49B69C1, $EFBE4786, ..
	                 $0FC19DC6, $240CA1CC, $2DE92C6F, $4A7484AA, $5CB0A9DC, $76F988DA, ..
	                 $983E5152, $A831C66D, $B00327C8, $BF597FC7, $C6E00BF3, $D5A79147, ..
	                 $06CA6351, $14292967, $27B70A85, $2E1B2138, $4D2C6DFC, $53380D13, ..
	                 $650A7354, $766A0ABB, $81C2C92E, $92722C85, $A2BFE8A1, $A81A664B, ..
	                 $C24B8B70, $C76C51A3, $D192E819, $D6990624, $F40E3585, $106AA070, ..
	                 $19A4C116, $1E376C08, $2748774C, $34B0BCB5, $391C0CB3, $4ED8AA4A, ..
	                 $5B9CCA4F, $682E6FF3, $748F82EE, $78A5636F, $84C87814, $8CC70208, ..
	                 $90BEFFFA, $A4506CEB, $BEF9A3F7, $C67178F2]
	
	local intCount:int = (((in.length + 8) shr 6) + 1) shl 4
	local data:int[intCount]
	
	for local c=0 until in.length
		data[c shr 2] = (data[c shr 2] shl 8) | (in[c] & $FF); next
	
	data[in.length shr 2] = ((data[in.length shr 2] shl 8) | $80) shl ((3 - (in.length & 3)) shl 3) 
	data[data.length - 2] = (long(in.length) * 8) shr 32
	data[data.length - 1] = (long(in.length) * 8) & $FFFFFFFF
	
	for local chunkStart = 0 until intCount step 16
	
		local a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7
		
		local w[] = data[chunkStart..chunkStart + 16]
		w = w[..64]
		
		for local i = 16 to 63
		
			w[i] = w[i - 16] + (ror(w[i - 15], 7) ~ Ror(w[i - 15], 18) ~ (w[i - 15] shr 3))..
				+ w[i - 7] + (Ror(w[i - 2], 17) ~ Ror(w[i - 2], 19) ~ (w[i - 2] shr 10))
		
		next
		
		for local i = 0 to 63
		
			local t0 = (Ror(a, 2) ~ Ror(a, 13) ~ Ror(a, 22)) + ((a & b) | (b & c) | (c & a))
			local t1 = h + (Ror(e, 6) ~ Ror(e, 11) ~ Ror(e, 25)) + ((e & f) | (~e & g)) + k[i] + w[i]
			
			h = g ; g = f ; f = e ; e = d + t1
			d = c ; c = b ; b = a ;  a = t0 + t1
		
		next
		
		h0 :+ a ; h1 :+ b ; h2 :+ c ; h3 :+ d
		h4 :+ e ; h5 :+ f ; h6 :+ g ; h7 :+ h
	
	next
	
	return (hex(h0) + hex(h1) + hex(h2) + hex(h3) + hex(h4) + hex(h5) + hex(h6) + hex(h7)).ToLower()

end function

'// -----------------------------------------------------------------------------------------------------------------
'// Description:
'//		Ror function.
'// 
'// Parameters:
'//		(int) val
'//		(int) shift
'// -----------------------------------------------------------------------------------------------------------------
function ror(val:int, shift:int)

	return (val shr shift) | (val shl (32 - shift))

end function
